home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / bin / ubiquity-dm < prev    next >
Text File  |  2008-10-29  |  11KB  |  271 lines

  1. #!/usr/bin/python
  2.  
  3. import os
  4. import sys
  5. import subprocess
  6. import time
  7. import signal
  8. import errno
  9. import imp
  10. import grp
  11.  
  12. sys.path.insert(0, '/usr/lib/ubiquity')
  13.  
  14. import ubiquity.frontend
  15. import pwd
  16.  
  17. from ubiquity import osextras
  18.  
  19. background = '/usr/share/backgrounds/warty-final-ubuntu.png'
  20.  
  21. class XStartupError(EnvironmentError):
  22.     pass
  23.  
  24. class MissingProgramError(EnvironmentError):
  25.     pass
  26.  
  27. class DM:
  28.     def __init__(self, vt, display):
  29.         self.vt = vt
  30.         self.display = display
  31.         self.server_started = False
  32.  
  33.         fp = open('/etc/casper.conf', 'r')
  34.         try:
  35.             for line in fp:
  36.                 if line.startswith('#'):
  37.                     continue
  38.                 line = line.split()
  39.                 if not line:
  40.                     continue
  41.                 if line[0] == 'export':
  42.                     w = line[1].split('=')
  43.                     if w[0] == 'USERNAME':
  44.                         self.username = w[1].strip('"')
  45.         except IOError:
  46.             import syslog
  47.             syslog.syslog('Unable to determine the username from /etc/casper.conf, using the default.')
  48.             self.username = 'ubuntu'
  49.         finally:
  50.             fp.close()
  51.         self.uid, self.gid = pwd.getpwnam(self.username)[2:4]
  52.         self.homedir = pwd.getpwnam(self.username)[5]
  53.         self.uid = int(self.uid)
  54.         self.gid = int(self.gid)
  55.         self.groups = []
  56.         for g in grp.getgrall():
  57.             if self.username in g[3] or g[0] == self.username:
  58.                 self.groups.append(g[2])
  59.  
  60.         # Look for a frontend module; we won't actually use it (yet), but
  61.         # this lets us find out which window manager etc. to launch. Be
  62.         # careful that importing this here will cause the underlying library
  63.         # to try to talk to the X server, which won't go well.
  64.         frontend_names = ['mythbuntu_ui', 'gtk_ui', 'kde_ui']
  65.         self.frontend = None
  66.         for f in frontend_names:
  67.             try:
  68.                 imp.find_module(f, ubiquity.frontend.__path__)
  69.                 self.frontend = f
  70.                 break
  71.             except ImportError:
  72.                 pass
  73.         else:
  74.             raise AttributeError, ('No frontend available; tried %s' %
  75.                                    ', '.join(frontend_names))
  76.  
  77.     def sigusr1_handler(self, signum, frame):
  78.         self.server_started = True
  79.  
  80.     def drop_privileges(self):
  81.         os.setgroups(self.groups)
  82.         os.setgid(self.gid)
  83.         os.setuid(self.uid)
  84.  
  85.     def server_preexec(self):
  86.         signal.signal(signal.SIGUSR1, signal.SIG_IGN)
  87.  
  88.     def run(self, *program):
  89.         null = open('/dev/null', 'w')
  90.         if not os.path.exists('/var/log/installer'):
  91.             os.makedirs('/var/log/installer')
  92.         logfile = open('/var/log/installer/dm', 'w')
  93.  
  94.         signal.signal(signal.SIGUSR1, self.sigusr1_handler)
  95.         signal.signal(signal.SIGTTIN, signal.SIG_IGN)
  96.         signal.signal(signal.SIGTTOU, signal.SIG_IGN)
  97.  
  98.         servercommand = ['X', '-br', '-ac', '-noreset', self.vt, self.display]
  99.         if self.frontend == 'mythbuntu_ui':
  100.             servercommand.append('-dpi')
  101.             servercommand.append('100')
  102.  
  103.         server = subprocess.Popen(servercommand, stdin=null, stdout=logfile, stderr=logfile, preexec_fn=self.server_preexec)
  104.  
  105.         os.environ['DISPLAY'] = self.display
  106.         os.environ['HOME'] = self.homedir
  107.  
  108.         # Really we should select on a pipe or something, but it's not worth
  109.         # the effort for now.
  110.         timeout = 60
  111.         while not self.server_started:
  112.             if timeout == 0:
  113.                 raise XStartupError, "X server failed to start after 60 seconds"
  114.             time.sleep(1)
  115.             timeout -= 1
  116.  
  117.         # Session bus, apparently needed by most interfaces now
  118.         if ('DBUS_SESSION_BUS_ADDRESS' not in os.environ and
  119.             osextras.find_on_path('dbus-launch')):
  120.             dbus_subp = subprocess.Popen(
  121.                 ['dbus-launch', '--exit-with-session'],
  122.                 stdin=null, stdout=subprocess.PIPE, stderr=logfile,
  123.                 preexec_fn=self.drop_privileges)
  124.             for line in dbus_subp.stdout:
  125.                 try:
  126.                     name, value = line.rstrip('\n').split('=', 1)
  127.                     os.environ[name] = value
  128.                 except ValueError:
  129.                     pass
  130.             dbus_subp.wait()
  131.  
  132.         gconfd_running = False
  133.         if ((self.frontend == 'gtk_ui' or self.frontend == 'mythbuntu_ui') and
  134.             osextras.find_on_path('gconftool-2')):
  135.             subprocess.call(['gconftool-2', '--spawn'],
  136.                             stdin=null, stdout=logfile, stderr=logfile,
  137.                             preexec_fn=self.drop_privileges)
  138.             gconfd_running = True
  139.  
  140.         extras = []
  141.         if self.frontend == 'gtk_ui' or self.frontend == 'mythbuntu_ui':
  142.             # Accessibility infrastructure
  143.             gconf_dir = ('xml:readwrite:%s' %
  144.                 '/root/.gconf')
  145.             accessibility = 'false'
  146.             if osextras.find_on_path('gconftool-2'):
  147.                 subp = subprocess.Popen(
  148.                     ['gconftool-2', '--config-source', gconf_dir,
  149.                      '--get', '/desktop/gnome/interface/accessibility'],
  150.                     stdout=subprocess.PIPE, stderr=subprocess.PIPE,
  151.                     preexec_fn=self.drop_privileges)
  152.                 accessibility = subp.communicate()[0].rstrip('\n')
  153.             if accessibility == 'true':
  154.                 if os.path.exists('/usr/lib/at-spi/at-spi-registryd'):
  155.                     extras.append(subprocess.Popen(['/usr/lib/at-spi/at-spi-registryd'],
  156.                         stdin=null, stdout=logfile, stderr=logfile))
  157.                     os.environ['GTK_MODULES'] = 'gail:atk-bridge'
  158.  
  159.             maybe_drop_privileges = {}
  160.             if accessibility != 'true':
  161.                 maybe_drop_privileges['preexec_fn'] = self.drop_privileges
  162.  
  163.             # Don't show the background image in v1 accessibility profile. It
  164.             # is not shown in the GNOME desktop after all.
  165.             fp = open('/proc/cmdline', 'r')
  166.             if os.access(background, os.R_OK) and not 'access=v1' in fp.readline():
  167.                 import gtk
  168.                 pixbuf = gtk.gdk.pixbuf_new_from_file(background)
  169.                 root = gtk.gdk.get_default_root_window()
  170.                 (root_width, root_height) = root.get_size()
  171.                 scaled = pixbuf.scale_simple(root_width, root_height, gtk.gdk.INTERP_BILINEAR)
  172.                 (pixmap, mask) = scaled.render_pixmap_and_mask(0)
  173.                 root.set_back_pixmap(pixmap, False)
  174.                 root.clear()
  175.                 gtk.gdk.flush()
  176.             fp.close()
  177.  
  178.         if self.frontend in ('gtk_ui', 'mythbuntu_ui'):
  179.             if gconfd_running and osextras.find_on_path('metacity'):
  180.                 wm = subprocess.Popen(['metacity', '--sm-disable'],
  181.                     stdin=null, stdout=logfile, stderr=logfile,
  182.                     **maybe_drop_privileges)
  183.             elif osextras.find_on_path('xfwm4'):
  184.                 wm = subprocess.Popen('xfwm4',
  185.                     stdin=null, stdout=logfile, stderr=logfile,
  186.                     **maybe_drop_privileges)
  187.             elif osextras.find_on_path('matchbox-window-manager'):
  188.                 wm = subprocess.Popen('matchbox-window-manager',
  189.                     stdin=null, stdout=logfile, stderr=logfile,
  190.                     **maybe_drop_privileges)
  191.             else:
  192.                 raise MissingProgramError, \
  193.                     "No window manager found (tried metacity, xfwm4, matchbox-window-manager)"
  194.  
  195.             if os.path.exists('/usr/lib/gnome-settings-daemon/gnome-settings-daemon'):
  196.                 extras.append(subprocess.Popen(['/usr/lib/gnome-settings-daemon/gnome-settings-daemon'],
  197.                     stdin=null, stdout=logfile, stderr=logfile, **maybe_drop_privileges))
  198.  
  199.             # Accessibility tools
  200.             if accessibility == 'true':
  201.                 fp = open('/proc/cmdline', 'r')
  202.                 if 'access=m2' in fp.readline():
  203.                     if osextras.find_on_path('onboard'):
  204.                         extras.append(subprocess.Popen(['onboard'],
  205.                             stdin=null, stdout=logfile, stderr=logfile))
  206.                 else:
  207.                     if osextras.find_on_path('orca'):
  208.                         time.sleep(15)
  209.                         extras.append(subprocess.Popen(['orca', '-n'],
  210.                             stdin=null, stdout=logfile, stderr=logfile))
  211.                 fp.close()
  212.         elif self.frontend == 'kde_ui':
  213.             extras.append(subprocess.Popen(['kwriteconfig', '--file', 'kwinrc', '--group', 'Compositing', '--key', 'Enabled', 'false'], stdin=null, stdout=logfile, stderr=logfile, preexec_fn=self.drop_privileges))
  214.             wm = subprocess.Popen('kwin', stdin=null, stdout=logfile,
  215.                 stderr=logfile, preexec_fn=self.drop_privileges)
  216.  
  217.         greeter = subprocess.Popen(program, stdin=null, stdout=logfile, stderr=logfile)
  218.         ret = greeter.wait()
  219.  
  220.         def sigalrm_handler(signum, frame):
  221.             os.kill(wm.pid, signal.SIGKILL)
  222.             for extra in extras:
  223.                 os.kill(extra.pid, signal.SIGKILL)
  224.  
  225.         os.kill(wm.pid, signal.SIGTERM)
  226.         for extra in extras:
  227.             os.kill(extra.pid, signal.SIGTERM)
  228.         if gconfd_running:
  229.             subprocess.call(['gconftool-2', '--shutdown'],
  230.                             stdin=null, stdout=logfile, stderr=logfile,
  231.                             preexec_fn=self.drop_privileges)
  232.         signal.signal(signal.SIGALRM, sigalrm_handler)
  233.         signal.alarm(1) # low patience with WMs failing to exit on demand
  234.         processes = set(extras)
  235.         processes.add(wm)
  236.         while processes:
  237.             done = set()
  238.             for process in processes:
  239.                 try:
  240.                     process.wait()
  241.                     done.add(process)
  242.                 except OSError, e:
  243.                     if e.errno == errno.EINTR:
  244.                         continue
  245.                     raise
  246.             processes -= done
  247.         signal.alarm(0)
  248.         os.kill(server.pid, signal.SIGTERM)
  249.         server.wait()
  250.  
  251.         if ret is not None and ret >= 0:
  252.             return ret
  253.         else:
  254.             return 1
  255.  
  256. if len(sys.argv) < 3:
  257.     sys.stderr.write('Usage: ubiquity-dm <vt[1-N]> <:[0-N]> <program> [<arguments>]\n')
  258.     sys.exit(1)
  259.  
  260. vt, display = sys.argv[1:3]
  261. dm = DM(vt, display)
  262. proc = None
  263. if dm.frontend == 'gtk_ui' or dm.frontend == 'mythbuntu_ui':
  264.     proc = ['/etc/init.d/gdm', 'start']
  265. elif dm.frontend == 'kde_ui':
  266.     proc = ['/etc/init.d/kdm', 'start']
  267. ret = dm.run(*sys.argv[3:])
  268. if proc:
  269.     subprocess.Popen(proc)
  270. sys.exit(ret)
  271.